package com.cycle.community.service;

import com.cycle.community.constant.CommunityConstant;
import com.cycle.community.entity.User;
import com.cycle.community.util.CommunityUtil;
import com.cycle.community.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author lenovo
 * @create 2022/8/16 10:41
 */
@Service
public class FollowService implements CommunityConstant {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserService userService;

    //关注
    public void follow(long userId, int entityType, long entityId) {
        //存两份数据，关注的目标和粉丝
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                operations.multi();
                operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());
                return operations.exec();
            }
        });
    }

    //取消关注
    public void unFollow(long userId, int entityType, long entityId) {
        //存两份数据，关注的目标和粉丝
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                operations.multi();
                operations.opsForZSet().remove(followeeKey, entityId);
                operations.opsForZSet().remove(followerKey, userId);
                return operations.exec();
            }
        });
    }

    //查询某用户关注的实体的数量
    public long findFolloweeCount(long userId, int entityType) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    //查询某实体的粉丝的数量
    public long findFollowerCount(int entityType, long entityId) {
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    //查询当前用户是否已关注该实体
    public boolean hasFollowed(long userId, int entityType, long entityId) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        //查分数是否存在来判断是否存在
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }

    //查询某用户关注的人
    public List<Map<String, Object>> findFollowees(long userId, int offset, int limit) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, ENTITY_TYPE_USER);
        //Redis自己实现的有序set集合
//        Set<Long> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);//包含offset
        Set initTargetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);//包含offset
        if (initTargetIds == null) {
            return null;
        }
//        Set<Long> targetIds = new TreeSet<>((o1, o2) -> o2.compareTo(o1));//应该要排序
        Set<Long> targetIds = new TreeSet<>(Comparator.reverseOrder());//应该要排序
        for (Object obj : initTargetIds) {
//            if (obj instanceof Integer) {
//                targetIds.add(((Integer) obj).longValue());
//            } else {
//                targetIds.add((Long) obj);
//            }
            targetIds.add(CommunityUtil.Integer2Long(obj));
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for (Long targetId : targetIds) {
            System.out.println(targetId);
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(followeeKey, targetId);//时间
            map.put("followTime", new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }

    //查询某用户的粉丝
    public List<Map<String, Object>> findFollowers(long userId, int offset, int limit) {
        String followerKey = RedisKeyUtil.getFollowerKey(ENTITY_TYPE_USER, userId);
        //Redis自己实现的有序set集合
//        Set<Long> targetIds = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);//包含offset
        Set initTargetIds = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);//包含offset
        if (initTargetIds == null) {
            return null;
        }
//        Set<Long> targetIds = new TreeSet<>((o1, o2) -> o2.compareTo(o1));//应该要排序
        Set<Long> targetIds = new TreeSet<>(Comparator.reverseOrder());//应该要排序
        for (Object obj : initTargetIds) {
//            if (obj instanceof Integer) {
//                targetIds.add(((Integer) obj).longValue());
//            } else {
//                targetIds.add((Long) obj);
//            }
            targetIds.add(CommunityUtil.Integer2Long(obj));
        }
        List<Map<String, Object>> list = new ArrayList<>();
        for (Long targetId : targetIds) {
            Map<String, Object> map = new HashMap<>();
            User user = userService.findUserById(targetId);
            map.put("user", user);
            Double score = redisTemplate.opsForZSet().score(followerKey, targetId);//时间
            map.put("followTime", new Date(score.longValue()));
            list.add(map);
        }
        return list;
    }
}
